<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
</head>

<body>
    <canvas id="canvas"></canvas>
</body>
<script id="ColorVertexShader" type="x-shader/x-vertex">
    attribute vec4 a_Position;
    uniform float u_PointSize;
    uniform mat4 u_ModelM4;
    uniform mat4 u_PvM4;
    void main(){
        gl_Position = u_PvM4 * u_ModelM4 * a_Position;
        gl_PointSize = u_PointSize;
    }
</script>
<script id="ColorFragmentShader" type="x-shader/x-fragment">
    precision mediump float;
    uniform vec4 u_Color;
    void main(){
        gl_FragColor = u_Color;
    }
</script>
<script type="module">
    import { Matrix4, Vector3, Color, OrthographicCamera, PerspectiveCamera, Spherical } from '../js/three.module.js';
    import { CreateProgram, imgPromise } from '../js/Utils.js';
    import lib from '../js/ThreeLib.js';
    import CameraController from '../js/CameraController.js'
    import Poly from '../js/Poly4.js'
    import Control from '../js/Control.js'

    import Geo from '../js/Poly2/Geo.js'
    import Mat from '../js/Poly2/Mat.js'
    import Obj3D from '../js/Poly2/Obj3D.js'
    import Scene from '../js/Poly2/Scene.js'



    //#region gl
    const canvas = document.getElementById("canvas");
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight - 4;

    const gl = canvas.getContext("webgl", { antialias: true, });

    // gl.enable(gl.DEPTH_TEST);//开始背景遮挡会频闪
    gl.enable(gl.BLEND);
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
    gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);//去图片描边
    //#endregion



    const scene = new Scene({ gl: gl });
    scene.regProgram('color', {
        program: CreateProgram(gl,
            document.querySelector('#ColorVertexShader').innerText,
            document.querySelector('#ColorFragmentShader').innerText),
        attribs: ['a_Position'],
        uniforms: ['u_PvM4', 'u_ModelM4', 'u_PointSize', 'u_Color']
    })

    const pvM4 = new Matrix4();
    const modelM4 = new Matrix4();
    const eye = new Vector3(2, 2, 1);
    const lookAt = new Vector3(0, 0, 0);

    const camera = new PerspectiveCamera(45, canvas.width / canvas.height, 1, 20);
    const cameraController = new CameraController({
        canvas, camera,
        pvMatrix: pvM4,
        eye, lookAt,
    });


    const diagramCount = 7;
    const diagramHeight = 0.2;

    const animArr = [];

    let curIndex = 0;

    const animDefaultData = {
        id: 0,//设置的ID
        state: 0,//状态
        beginTime: 0,
        distTime: 1000,//持续时间
        from: 0,
        to: 0,
        actionIng: (num, data) => { },//执行的回调
        actionEnd: (data) => { },//结束后的回调
    };


    //main

    createDiagram();
    update(0)

    function update(index) {
        const distTime = 200;
        //过渡
        addAnim({
            id: 0,
            distTime: distTime,
            from: eye.clone(),
            to: new Vector3(eye.x, index * diagramHeight + 1, eye.z),
            actionIng: (num, data) => {
                const { from, to } = data;
                eye.copy(new Vector3(
                    (to.x - from.x) * num + from.x,
                    (to.y - from.y) * num + from.y,
                    (to.z - from.z) * num + from.z
                ));
                cameraController.setEye(eye);
            },
        });
        addAnim({
            id: 1,
            distTime: distTime,
            from: lookAt.clone(),
            to: new Vector3(lookAt.x, index * diagramHeight, lookAt.z),
            actionIng: (num, data) => {
                const { from, to } = data;
                lookAt.copy(new Vector3(
                    (to.x - from.x) * num + from.x,
                    (to.y - from.y) * num + from.y,
                    (to.z - from.z) * num + from.z
                ));
                cameraController.setLookAt(lookAt);
            },
        });
        //这一个放大
        addAnim({
            id: 2,
            distTime: distTime,
            from: 1,
            to: 1.5,
            actionIng: (num, data) => {
                const { from, to } = data;
                const scale = (to - from) * num + from;
                scene.children[index].setUniform('u_ModelM4', { value: new Matrix4().makeScale(scale, 1, scale).elements })
            },
        });
        //上一个缩小
        addAnim({
            id: 2,
            distTime: distTime,
            from: 1.5,
            to: 1,
            actionIng: (num, data) => {
                const { from, to } = data;
                const scale = (to - from) * num + from;
                let curindex = index - 1;
                if (curindex < 0) {
                    curindex = 6;
                }
                scene.children[curindex].setUniform('u_ModelM4', { value: new Matrix4().makeScale(scale, 1, scale).elements })
            },
        });
    }

    function addAnim(data) {
        data.state = 0;
        for (let i = 0; i < animArr.length; i++) {
            if (data.id == animArr[i]) {
                animArr[i].state = data.state;
                animArr[i].distTime = data.distTime;
                animArr[i].from = data.from;
                animArr[i].to = data.to;
                return;
            }
        }
        animArr.push(data);
    }

    function createDiagram() {
        for (let i = 0; i < diagramCount; i++) {
            let obj = createFace(getNodeArr(i), [Math.random(), Math.random(), Math.random(), 1]);
            scene.add(obj);
        }
    }

    function getNodeArr(index) {
        const nodeLength = 0.3;
        const height = index * diagramHeight;
        const nodeArr = [
            -nodeLength, height, -nodeLength,
            -nodeLength, height, nodeLength,
            nodeLength, height, nodeLength,
            nodeLength, height, -nodeLength,
        ];
        return nodeArr;
    }

    function createFace(nodeArr, color) {
        return new Obj3D({
            geo: new Geo({
                data: {
                    'a_Position': { size: 3, array: new Float32Array(nodeArr) },
                },
                element: {
                    array: new Uint8Array([0, 1, 2, 0, 2, 3])
                }
            }),
            mat: new Mat({
                program: 'color',
                mode: ['TRIANGLES'],
                data: {
                    'u_PvM4': { type: 'uniformMatrix4fv', value: pvM4.elements },
                    'u_ModelM4': { type: 'uniformMatrix4fv', value: modelM4.elements },
                    'u_PointSize': { type: 'uniform1f', value: 30 },
                    'u_Color': { type: 'uniform4fv', value: color },
                },
            }),
        });
    }


    let s = 0.005;
    let countSet = 0;
    (function ani(time) {
        countSet += s;
        if (countSet > 1) {
            countSet = 0;

            curIndex++;
            update(curIndex % diagramCount);
        }

        animUpdate(time);

        draw();
        requestAnimationFrame(ani);
    })(0);

    function animUpdate(time) {
        for (let i = 0; i < animArr.length; i++) {
            if (animArr[i].state == 0) {
                animArr[i].state = 1;
                animArr[i].beginTime = time;
            }
            if (animArr[i].state == 1) {
                const { actionIng, beginTime, distTime } = animArr[i];
                if (beginTime + distTime < time) {
                    animArr[i].state = 2;
                } else {
                    const num = (time - beginTime) / distTime;
                    actionIng(num, animArr[i]);
                }
            }
            if (animArr[i].state == 2) {
                const { actionIng } = animArr[i];
                actionIng(1, animArr[i]);
                animArr.splice(i, 1);
                i--;
            }
        }

        // console.log(animArr.length)
    }

    function draw() {
        scene.setUniform('u_PvM4', { value: pvM4.elements })
        scene.draw();
    }
</script>

</html>